/**
 * @author Austin Andrews (Templarian)
 * @authorurl http://templarian.com
 * @framework DD Framework
 * @licence MIT License
 * @licenceurl http://ddframework.googlecode.com/svn/trunk/license.txt
 * @overview The http module is used to handle the passing and loading of data 
 * to a server without refreshing the page. Use dd.xml(string) for parsing xml
 * out of the `this.json` or `this.text`.
 */
dd.http({
    /**
     * Use as a function to make data requests with both get and post data.
     * @namespace dd.http
     * @function
     *  Use to pass data to the server and recieve a value in JSON, XML, or plain text.
     *  @param obj {object} Contains the get, post, url variables and success, failure Callbacks.
     *  @returns {object} With an .abort() function
     *  ```javascript
     *  dd.http({
     *      url:"",               // URL
     *      type:"GET"            // Only Needed for "PUT" and "DELETE" requests
     *      get:{},               // Get Parameters (optional)
     *      post:{},              // Post Parameters (optional)
     *      success:function(){}, // Success
     *      failure:function(){}  // Failure
     *  });
     *  ```
     * @function
     *  Use to pass data to the server and recieve a value in JSON, XML, or plain text.
     *  @param obj {object} Contains the get, post, url variables and Success, Failure Callbacks.
     *  @param scope {object} Variables to be append to the scope of the Success, Failure Callbacks.
     *  @returns {object} With an .abort() function
     */
    func:function(o, s)
    {
        s = s || {};
        var m = o.type || "GET",
            p = true,
            g = true,
            get = "",
            post = "",
            time = 0,
            req = new XMLHttpRequest();
        if(!o.hasOwnProperty("scope"))
        {
            o.scope = this;
        }
        if(!o.hasOwnProperty("time"))
        {
            o.time = false;
        }
        if(o.hasOwnProperty("post") || m == "PUT" || m == "DELETE")
        {
            if(!(m == "PUT" || m == "DELETE"))
            {
                m = "POST";
            }
            for(var i in o.post)
            {
                post += (p ? "" : "&") + i + "=" + encodeURIComponent(o.post[i]);
                p = false;
            }
        }
        if(o.hasOwnProperty("get"))
        {
            for(var i in o.get)
            {
                get += (g ? "?" : "&")
                    + i
                    + "="
                    + encodeURIComponent(typeof(o.get[i]) == "object" ? dd.json(o.get[i]) : o.get[i]);
                g = false;
            }
        }
        if(o.hasOwnProperty("type"))
        {
            m = o.type;
        }
        req.onreadystatechange = function()
        {
            if(req.readyState == 4)
            {
                if(req.status == 200)
                {
                    var obj = {
                        file:o.url,
                        status:req.status,
                        statusText:req.statusText,
                        text:req.responseText,
                        time:(new Date).getTime() - time
                    };
                    try{
                        obj.json = dd.json(req.responseText);
                    }catch(e){}
                    dd.extend(obj, s);
                    if("success" in o)
                    {
                        o.success.call(obj);
                    }
                }
                else
                {
                    if("failure" in o)
                    {
                        var obj = {
                            status:req.status,
                            statusText:req.statusText,
                            time:(new Date).getTime() - time,
                            text: req.responseText
                        };
                        try{
                            obj.json = dd.json(req.responseText);
                        }catch(e){}
                        dd.extend(obj, s);
                        o.failure.call(obj);
                    }
                }
            }
        };
        req.open(m, o.url + get, true);
        if(post != "")
        {
            req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
        }
        req.send(m == "GET" ? null : post);
        time = (new Date).getTime();
        return {abort:(function(req){return function(){req.abort();}})(req)}
    },
    /**
     * Use as a function to read in a url's data
     * @namespace dd.http.open
     * @function
     *  Use to request data from a url
     *  @param url {string} The address
     *  @param success {function} Use this.text to get the response
     *  @param failure {function} Use this.text to get the response and this.status for the status.
     *  @returns {object} With an .abort() function
     *  ```javascript
     *  dd.http.open(""     // URL
     *      function(){},   // success
     *      function(){});  // failure
     *  ```
     */
    open:function(url, success, failure)
    {
        return this({
            url:url,
            success:success,
            failure:failure
        });
    }
});